package com.laikan.reader.bookreader.engines;

import android.content.Context;
import android.graphics.*;
import android.graphics.Paint.Style;
import android.graphics.Shader.TileMode;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.widget.RelativeLayout;
import com.laikan.library.managers.ToastMgr;
import com.laikan.library.utils.AndroidUtils;
import com.laikan.reader.core.utils.ActivityUitl;

import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;

/**
 * Created by wx
 *
 * @date 2016/5/25/14:55
 * @description
 */
public class ScanView extends RelativeLayout {

    public static final String TAG = "ScanView";

    public boolean isMoveInit = false;
    private boolean isInit = true;
    // 滑动的时候存在两页可滑动，要判断是哪一页在滑动
    private boolean isPreMoving = true, isCurrMoving = true;
    private boolean isPreMoveSingle = true, isCurrMoveSingle = true;
    private float lastX;
    // 前一页，当前页，下一页的左边位置
    private int prePageLeft = 0, currPageLeft = 0, nextPageLeft = 0;
    // 三张页面
    public PageView prePage, currPage, nextPage;
    // 页面状态
    private static final int STATE_MOVE = 0;
    private static final int STATE_STOP = 1;
    // 滑动的页面，只有前一页和当前页可滑
    private static final int PRE = 2;
    private static final int CURR = 3;
    private int state = STATE_STOP;
    // 正在滑动的页面右边位置，用于绘制阴影
    private float right;
    // 手指滑动的距离
    private float moveLenght;
    // 页面宽高
    private int mWidth, mHeight;
    // 获取滑动速度
    private VelocityTracker vt;
    // 防止抖动
    private float speed_shake = 5;
    // 当前滑动速度
    private float speed;
    private MyTimerTask mTask;
    private Timer timer;
    // 滑动动画的移动速度
    public  int MOVE_SPEED = 5;
    // 页面适配器
    private ScanViewAdapter adapter;
    /**
     * 过滤多点触碰的控制变量
     */

    private long INTERVAL = 300;
    private int mEvents;
    List<Vector<WordLinePos>> pages;
    private long MoveClickTime = 0L; // 上一次点击的时间
    private RectF mMenuRect,mleftRect,mrightRect;
    private long touchClickTime = 0L; // 上一次点击的时间


    /**
     * 控制【下一章按钮】点击频率，即控制点击间隔时间。
     *
     * @return
     */
    public boolean touchClickPage() {
        long time = System.currentTimeMillis();
        if ((time - touchClickTime) > INTERVAL) {
            touchClickTime = time;
            return true;
        }

        return false;
    }
    private InteractiveEvent inEnevt;//互动区域点击事件
    private Handler  handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if(msg.what == 1){
                removeView(prePage);
                addView(prePage, 0, new LayoutParams(LayoutParams.MATCH_PARENT,
                    LayoutParams.MATCH_PARENT));
                // 从适配器获取后一页内容
                adapter.refreshPage(prePage, 1);
                // 交换顺序
                PageView temp = currPage;
                currPage = nextPage;
                nextPage = prePage;
                prePage = temp;
                currPageLeft = 0;
                isDrag = false;
            }else if(msg.what == 2){
                removeView(nextPage);
                addView(nextPage, -1, new LayoutParams(LayoutParams.MATCH_PARENT,
                    LayoutParams.MATCH_PARENT));
                // 从适配器获取前一页内容
                adapter.refreshPage(nextPage, 0);
                // 交换顺序
                PageView temp = nextPage;
                nextPage = currPage;
                currPage = prePage;
                prePage = temp;
                prePageLeft = -mWidth;
                isDrag = false;
            }else if(msg.what == 3){
               ToastMgr.showShortToast(com.laikan.reader.R.string.net_connect_error);
            }
            requestLayout();
        }
    };

    public void setInEnevt(InteractiveEvent inEnevt) {
        this.inEnevt = inEnevt;
    }
    /**
     * 最大抖动位移
     */
    public final int FLING_MAX_SHAKE = 50;
    private OnMenuListener onMenuListener;
    RectF reward, comment, share;
    public void setAdapter(ScanViewAdapter adapter, int screenWidth, int screenHeight) {
        MOVE_SPEED = AndroidUtils.dip2px(getContext(),2.5f);
        removeAllViews();
        float iocnMarTop = 1182f / 1280 * mHeight;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            int actionbar = AndroidUtils.getVirtualKeyHeight(getContext());
            iocnMarTop = iocnMarTop - actionbar;
        }
        reward = new RectF(0, iocnMarTop, mWidth / 3, mHeight);
        comment = new RectF(mWidth / 3 * 1, iocnMarTop, mWidth / 3 * 2, mHeight);
        share = new RectF(mWidth / 3 * 2, iocnMarTop, mWidth, mHeight);

        mMenuRect = new RectF(screenWidth / 3, 0, screenWidth / 3 * 2, screenHeight);
        mleftRect  = new RectF(0, 0, screenWidth / 3, screenHeight);;
        mrightRect  = new RectF(screenWidth / 3* 2, 0, screenWidth, screenHeight);;
        this.adapter = adapter;
        prePage = adapter.getView(adapter.getIndex()-1,0);
        addView(prePage, 0, new LayoutParams(LayoutParams.MATCH_PARENT,
            LayoutParams.MATCH_PARENT));

        currPage = adapter.getView(adapter.getIndex(),1);
        addView(currPage, 0, new LayoutParams(LayoutParams.MATCH_PARENT,
            LayoutParams.MATCH_PARENT));

        nextPage = adapter.getView(adapter.getIndex() + 1,2);
        addView(nextPage, 0, new LayoutParams(LayoutParams.MATCH_PARENT,
            LayoutParams.MATCH_PARENT));
    }



    /**
     * 向左滑。注意可以滑动的页面只有当前页和前一页
     *
     * @param which
     */
    private void moveLeft(int which) {
        switch(which) {
            case PRE:
                prePageLeft -= MOVE_SPEED;
                if(prePageLeft < -mWidth) {
                    prePageLeft = -mWidth;
                }
                right = mWidth + prePageLeft;
                break;
            case CURR:
                currPageLeft -= MOVE_SPEED;
                if(currPageLeft < -mWidth) {
                    currPageLeft = -mWidth;
                }
                right = mWidth + currPageLeft;
                break;
        }
    }

    /**
     * 向右滑。注意可以滑动的页面只有当前页和前一页
     *
     * @param which
     */
    private void moveRight(int which) {
        switch(which) {
            case PRE:
                prePageLeft += MOVE_SPEED;
                if(prePageLeft > 0) {
                    prePageLeft = 0;
                }
                right = mWidth + prePageLeft;
                break;
            case CURR:
                currPageLeft += MOVE_SPEED;
                if(currPageLeft > 0) {
                    currPageLeft = 0;
                }
                right = mWidth + currPageLeft;
                break;
        }
    }

    /**
     * 当往回翻过一页时添加前一页在最左边
     */
    public void addPrePage() {

       handler.sendEmptyMessage(2);
    }

    /**
     * 当往前翻过一页时，添加一页在最底下
     */
    public void addNextPage() {
       handler.sendEmptyMessage(1);
    }

    Handler updateHandler = new Handler() {

        @Override
        public void handleMessage(Message msg) {
            if(state != STATE_MOVE) {
                isDrag = false;
                return;
            }
            // 移动页面
            // 翻回，先判断当前哪一页处于未返回状态
            if(prePageLeft > -mWidth && speed <= 0 && isPreMoveSingle) {
                // 前一页处于未返回状态
                moveLeft(PRE);
            }else if(currPageLeft < 0 && speed >= 0 && isCurrMoveSingle) {
                // 当前页处于未返回状态
                moveRight(CURR);
            }else if(speed < 0 && adapter.isNextPage(1) && isCurrMoveSingle) {
                // 向左翻，翻动的是当前页
                moveLeft(CURR);
                if(currPageLeft == (-mWidth)) {
                    // 翻过一页，在底下添加一页，把最上层页面移除
                    new Thread(){
                        @Override
                        public void run() {
                            super.run();
                            adapter.addIndex();
                            addNextPage();
                        }
                    }.start();

                }
            }else if(speed > 0 && adapter.isPrePage() && isPreMoveSingle) {
                // 向右翻，翻动的是前一页
                moveRight(PRE);
                if(prePageLeft == 0) {
                    // 翻回一页，添加一页在最上层，隐藏在最左边
                    new Thread(){
                        @Override
                        public void run() {
                            super.run();
                            adapter.minusIndex();
                            addPrePage();
                        }
                    }.start();

                }
            }
            if((right == 0) || right == mWidth) {
                releaseMoving();
                state = STATE_STOP;
                quitMove();
                isDrag = false;
            }
            ScanView.this.requestLayout();
        }

    };

    public ScanView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    public ScanView(Context context) {
        super(context);
        init();
    }

    public ScanView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    /**
     * 退出动画翻页
     */
    public void quitMove() {
        if(mTask != null) {
            mTask.cancel();
            mTask = null;
        }
    }

    private void init() {

        timer = new Timer();
        mTask = new MyTimerTask(updateHandler);
    }

    /**
     * 释放动作，不限制手滑动方向
     */
    private void releaseMoving() {
        isPreMoving = true;
        isCurrMoving = true;
    }

    /**
     * 开始按下的位置1
     */
    protected PointF ed1 = new PointF();
    /**
     * 开始按下的位置2
     */
    protected PointF ed2 = new PointF();
    /**
     * 移动中的位置
     */
    protected PointF em = new PointF();
    /**
     * 单页移动
     */
    protected boolean isMoveSing = true;
    //手指拖拽
    protected boolean isDrag = false;

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {

        if(adapter != null && isMoveInit) {
            switch(event.getActionMasked()) {
                case MotionEvent.ACTION_DOWN:
                    if(!touchClickPage()){
                        return false;
                    }
                    if(isDrag){
                        return true;
                    }
                    isDrag = false;
                    isPreMoveSingle = true;
                    isCurrMoveSingle = true;
                    lastX = event.getX();
                    try {
                        if(vt == null) {
                            vt = VelocityTracker.obtain();

                        }else {
                            vt.clear();
                        }
                        vt.addMovement(event);
                    }catch(Exception e) {
                        e.printStackTrace();
                    }

                    mEvents = 0;
//                    isDrag = false;

                    ed1 = new PointF(event.getX(), event.getY());
                    break;
                case MotionEvent.ACTION_POINTER_DOWN:

                case MotionEvent.ACTION_POINTER_UP:
                    mEvents = -1;
                    break;
                case MotionEvent.ACTION_MOVE:

                    float tt = event.getX() - ed1.x;
                    if(Math.abs(tt) > FLING_MAX_SHAKE) {
                        isDrag = true;
                        // 取消动画
                        quitMove();
                        if(vt!=null){
                            vt.addMovement(event);
                            vt.computeCurrentVelocity(500);
                            speed = vt.getXVelocity();
                        }
                        //
                        moveLenght = event.getX() - lastX;
                        if(event.getX() == ed1.x) {
                            isMoveSing = false;
                        }
                        if((moveLenght > 0 || !isCurrMoving) && isPreMoving
                           && mEvents == 0 && isPreMoveSingle) {
                            /***向右拖动 */
                            isPreMoveSingle = true;
                            isCurrMoveSingle = false;
                            isPreMoving = true;
                            isCurrMoving = false;
                            if(!adapter.isPrePage()) {
                                // 第一页不能再往右翻，跳转到前一个activity
                                state = STATE_MOVE;
                                releaseMoving();
                            }else {
                                // 非第一页
                                prePageLeft = (int) (event.getX() - mWidth);
                                // 防止滑过边界
                                if(prePageLeft > 0) {
                                    prePageLeft = 0;
                                }else if(prePageLeft < -mWidth) {
                                    // 边界判断，释放动作，防止来回滑动导致滑动前一页时当前页无法滑动
                                    prePageLeft = -mWidth;
                                    releaseMoving();
                                }
                                right = mWidth + prePageLeft;
                                state = STATE_MOVE;
                            }
                        }else if((moveLenght < 0 || !isPreMoving) && isCurrMoving
                                 && mEvents == 0 && isCurrMoveSingle) {
                            /***向左拖动 */
                            isPreMoveSingle = false;
                            isCurrMoveSingle = true;
                            isPreMoving = false;
                            isCurrMoving = true;
                            if(!adapter.isNextPage(0)) {
                                // 最后一页不能再往左翻
                                state = STATE_STOP;
                                releaseMoving();
                            }else {
                                currPageLeft += (int) moveLenght;
                                // 防止滑过边界
                                if(currPageLeft < -mWidth) {
                                    currPageLeft = -mWidth;
                                }else if(currPageLeft > 0) {
                                    // 边界判断，释放动作，防止来回滑动导致滑动当前页是前一页无法滑动
                                    currPageLeft = 0;
                                    releaseMoving();
                                }
                                right = mWidth + currPageLeft;
                                state = STATE_MOVE;
                            }

                        }else {
                            mEvents = 0;
                        }
                        lastX = event.getX();
                        requestLayout();

                    }

                    break;
                case MotionEvent.ACTION_UP:

                    if(!isDrag) {
                        if (clickRanges(event.getX(), event.getY())) {
                            return true;
                        }else if(mMenuRect.contains(event.getX(), event.getY())) {
                            if(onMenuListener!=null){
                                onMenuListener.setShowMenuListener();
                            }
                            return true;
                        }else if(mleftRect.contains(event.getX(), event.getY())){

                                    if(adapter.isPrePage()){
                                        adapter.minusIndex();
                                        addPrePage();
                                    }



                        }else if(mrightRect.contains(event.getX(), event.getY())){
                                    if(adapter.isNextPage(0)){
                                        adapter.addIndex();
                                        addNextPage();
                                    }

                        }
                    }else{
                        if(Math.abs(speed) < 0) {
                            speed = 0;
                        }
                        quitMove();
                        mTask = new MyTimerTask(updateHandler);
                        timer.schedule(mTask, 0, 1);
                        try {
                            //                        vt.clear();
                            //                        vt.recycle();
                        }catch(Exception e) {
                            e.printStackTrace();
                        }
                    }


                    break;
                default:
                    break;
            }
        }
        super.dispatchTouchEvent(event);

        return true;
    }

    public boolean clickRanges(float x2, float y2) {
        if (adapter.isCurrChapterLastPage()) {

            if (reward.contains(x2, y2)) { // 章末交互打赏
                if(ActivityUitl.isNetworkAvailable(getContext())){
                    inEnevt.fight();
                }else{
                    handler.sendEmptyMessage(3);
                }

                return true;
            }else if (comment.contains(x2, y2)) { // 章末交互评论
                if(ActivityUitl.isNetworkAvailable(getContext())) {
                    inEnevt.comment();
                }else{
                    handler.sendEmptyMessage(3);
                }
                return true;
            }else if (share.contains(x2, y2)) { //  章末交互分享
                inEnevt.getShare();
                return true;
            }
        }

        return false;
    }
    /*
     * （非 Javadoc） 在这里绘制翻页阴影效果
     *
     * @see android.view.ViewGroup#dispatchDraw(android.graphics.Canvas)
     */
    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);
        if(right <= 80 || right == mWidth) {
            return;
        }
        RectF rectF = new RectF(right, 0, mWidth, mHeight);
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        LinearGradient linearGradient = new LinearGradient(right, 0, right + 10, 0, 0xff959595, 0x00959595, TileMode.CLAMP);
        paint.setShader(linearGradient);
        paint.setStyle(Style.FILL);
        canvas.drawRect(rectF, paint);
    }



    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mWidth = getMeasuredWidth();
        mHeight = getMeasuredHeight();
        if(isInit) {
            // 初始状态，一页放在左边隐藏起来，两页叠在一块
            prePageLeft = -mWidth;
            currPageLeft = 0;
            nextPageLeft = 0;
            isInit = false;
        }
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        if(adapter == null) {
            return;
        }
        if(prePage == null || currPage == null || nextPage == null) {
            return;
        }
        prePage.layout(prePageLeft, 0,
            prePageLeft + prePage.getMeasuredWidth(),
            prePage.getMeasuredHeight());
        currPage.layout(currPageLeft, 0,
            currPageLeft + currPage.getMeasuredWidth(),
            currPage.getMeasuredHeight());
        nextPage.layout(nextPageLeft, 0,
            nextPageLeft + nextPage.getMeasuredWidth(),
            nextPage.getMeasuredHeight());
        invalidate();
    }

    class MyTimerTask extends TimerTask {

        Handler handler;

        public MyTimerTask(Handler handler) {
            this.handler = handler;
        }

        @Override
        public void run() {
            handler.sendMessage(handler.obtainMessage());
        }

    }

    public interface OnMenuListener{
        void setShowMenuListener();
    }
    public void setOnMenuListener(OnMenuListener l){
        this.onMenuListener = l;
    }
}
